// redis/redis.service.ts
import { Inject, Injectable, Logger } from '@nestjs/common';
import Redis from 'ioredis';

@Injectable()
export class RedisService {
  private readonly logger = new Logger(RedisService.name);

  constructor(@Inject('REDIS_CLIENT') private readonly redisClient: Redis) {}

  // 基础字符串操作
  async set(key: string, value: string, ttl?: number): Promise<boolean> {
    try {
      const result = ttl
        ? await this.redisClient.set(key, value, 'EX', ttl)
        : await this.redisClient.set(key, value);
      return result === 'OK';
    } catch (error) {
      this.logger.error(`Failed to set key ${key}: ${error.message}`);
      throw error;
    }
  }

  async get(key: string): Promise<string | null> {
    try {
      return await this.redisClient.get(key);
    } catch (error) {
      this.logger.error(`Failed to get key ${key}: ${error.message}`);
      throw error;
    }
  }

  // 对象操作（自动 JSON 序列化）
  async setObject(key: string, value: any, ttl?: number): Promise<boolean> {
    try {
      const json = JSON.stringify(value);
      return await this.set(key, json, ttl);
    } catch (error) {
      this.logger.error(`Failed to set object ${key}: ${error.message}`);
      throw error;
    }
  }

  async getObject<T>(key: string): Promise<T | null> {
    try {
      const json = await this.get(key);
      return json ? JSON.parse(json) : null;
    } catch (error) {
      this.logger.error(`Failed to get object ${key}: ${error.message}`);
      throw error;
    }
  }

  // 键管理
  async delete(key: string): Promise<number> {
    try {
      return await this.redisClient.del(key);
    } catch (error) {
      this.logger.error(`Failed to delete key ${key}: ${error.message}`);
      throw error;
    }
  }

  async exists(key: string): Promise<boolean> {
    try {
      const count = await this.redisClient.exists(key);
      return count > 0;
    } catch (error) {
      this.logger.error(`Failed to check key ${key}: ${error.message}`);
      throw error;
    }
  }

  async expire(key: string, ttl: number): Promise<boolean> {
    try {
      const result = await this.redisClient.expire(key, ttl);
      return result === 1;
    } catch (error) {
      this.logger.error(`Failed to set expire ${key}: ${error.message}`);
      throw error;
    }
  }

  async getKeys(pattern: string): Promise<string[]> {
    try {
      return await this.redisClient.keys(pattern);
    } catch (error) {
      this.logger.error(
        `Failed to get keys by pattern ${pattern}: ${error.message}`,
      );
      throw error;
    }
  }

  // 高级操作
  async increment(key: string, amount = 1): Promise<number> {
    try {
      return amount === 1
        ? await this.redisClient.incr(key)
        : await this.redisClient.incrby(key, amount);
    } catch (error) {
      this.logger.error(`Failed to increment key ${key}: ${error.message}`);
      throw error;
    }
  }

  async decrement(key: string, amount = 1): Promise<number> {
    try {
      return amount === 1
        ? await this.redisClient.decr(key)
        : await this.redisClient.decrby(key, amount);
    } catch (error) {
      this.logger.error(`Failed to decrement key ${key}: ${error.message}`);
      throw error;
    }
  }

  // 连接管理
  async disconnect(): Promise<void> {
    try {
      await this.redisClient.quit();
    } catch (error) {
      this.logger.error(`Failed to disconnect Redis: ${error.message}`);
      throw error;
    }
  }
}
